home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / comm / tcp / Amster.lha / Amster_Install / Source / thread.c < prev    next >
C/C++ Source or Header  |  2000-07-31  |  4KB  |  269 lines

  1. /*
  2. ** Threading Functions
  3. */
  4.  
  5. #include "include/config.h"
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #include <proto/exec.h>
  11. #include <proto/dos.h>
  12. #include <dos/dostags.h>
  13.  
  14. #include "include/thread.h"
  15. #include "include/protos.h"
  16.  
  17. struct MsgPort *th_mother=NULL;
  18. thread th_list=NULL;
  19. u_long th_sigmask=0;
  20.  
  21. void th_handlemsg(thmsg m);
  22. void th_cleanup(thread t);
  23.  
  24.  
  25. int th_init(void)
  26. {
  27.     th_mother = CreateMsgPort();
  28.     if (!th_mother) return(0);
  29.     th_sigmask = 1L << (th_mother->mp_SigBit);
  30.     return(1);
  31. }
  32.  
  33.  
  34. void th_exit(void)
  35. {
  36.     thread t;
  37.  
  38.     t = th_list;
  39.     while (t) {
  40.         th_message(t, THC_EXIT, 0);
  41.         t = t->next;
  42.     }
  43.  
  44.     while (th_list) {
  45.         thmsg m;
  46.         WaitPort(th_mother);
  47.         m = (thmsg)GetMsg(th_mother);
  48.         th_handlemsg(m);
  49.     }
  50.  
  51.     DeleteMsgPort(th_mother);
  52.     th_sigmask = 0;
  53. }
  54.  
  55.  
  56. thread th_spawn(thcb handler, char *name, void (*func)(void), int pri, APTR data)
  57. {
  58.     thread t;
  59.  
  60.     t = malloc(sizeof(_thread));
  61.     if (!t) return(NULL);
  62.     memset(t, 0, sizeof(_thread));
  63.  
  64.     t->task = (struct Task *)CreateNewProcTags(
  65.         NP_Entry, func,
  66.         NP_Name, name,
  67.         NP_StackSize, 8192,
  68.         NP_Priority, pri,
  69.         TAG_DONE);
  70.  
  71.     if (!t->task) {
  72.         free(t);
  73.         return(NULL);
  74.     }
  75.  
  76.     t->handler = handler;
  77.     t->mother = th_mother;
  78.     t->data = data;
  79.  
  80.     t->sm.header.mn_ReplyPort = th_mother;
  81.     t->sm.header.mn_Length = sizeof(_thmsg);
  82.     t->sm.com = THC_STARTUP;
  83.     t->sm.data = t;
  84.  
  85.     /* Begin new stuff */
  86.     t->task->tc_UserData = &t->sm;
  87.     t->mother_task = FindTask(NULL);
  88.     SetSignal(0L, SIGF_SINGLE);
  89.     Signal(t->task, SIGF_SINGLE);
  90.     Wait(SIGF_SINGLE);
  91.     /* End new stuff */
  92.  
  93.     /* Old stuff
  94.     PutMsg(&((struct Process *)t->task)->pr_MsgPort,(struct Message *)&t->sm);
  95.        End old stuff */
  96.  
  97.     /* Begin new stuff */
  98.     if (handler)    (handler)(t, THC_STARTUP, data);
  99.     /* End new stuff */
  100.  
  101.     t->next = th_list;
  102.     th_list = t;
  103.     return(t);
  104. }
  105.  
  106.  
  107. void th_message(thread t, int com, APTR data)
  108. {
  109.     thmsg m;
  110.  
  111.     if (!t) return;
  112.     if (!t->port) return;
  113.  
  114.     m = malloc(sizeof(_thmsg));
  115.     if (!m) return;
  116.     memset(m,0,sizeof(_thmsg));
  117.  
  118.     m->header.mn_ReplyPort = th_mother;
  119.     m->header.mn_Length = sizeof(_thmsg);
  120.     m->com = com;
  121.     m->data = data;
  122.  
  123.     PutMsg(t->port,(struct Message *)m);
  124. }
  125.  
  126.  
  127. void th_poll(void)
  128. {
  129.     thread t;
  130.     thmsg m;
  131.  
  132.     while(1) {
  133.         m = (thmsg)GetMsg(th_mother);
  134.         if(!m) break;
  135.  
  136.         if(m->com != THC_FINISH && (!m->isreply)) {
  137.             t = m->sender;
  138.             if(t && t->handler)
  139.                 (t->handler)(t,m->com,m->data);
  140.         }
  141.  
  142.         th_handlemsg(m);
  143.     }
  144. }
  145.  
  146.  
  147. thread thr_init(void)
  148. {
  149.     thread t;
  150.     thmsg m;
  151.     struct Task *me = FindTask(NULL);
  152.  
  153.     /* Begin new stuff */
  154.     Wait(SIGF_SINGLE);
  155.     m = (thmsg)me->tc_UserData;
  156.     t = (thread)m->data;
  157.  
  158.     t->port = CreateMsgPort();
  159.     if (!t->port) {
  160.         me->tc_UserData = (APTR)FALSE;
  161.         t = NULL;
  162.     }
  163.     else {
  164.         me->tc_UserData = (APTR)TRUE;
  165.         m->sender = t;
  166.     }
  167.     Signal(t->mother_task, SIGF_SINGLE);
  168.     /* End new stuff */
  169.  
  170.     /* Begin old stuff
  171.     WaitPort(&((struct Process *)me)->pr_MsgPort);
  172.     m = (thmsg)GetMsg(&((struct Process *)me)->pr_MsgPort);
  173.     t = m->data;
  174.  
  175.     t->port = CreateMsgPort();
  176.     if (!t->port) return(NULL);
  177.  
  178.     m->sender = t;
  179.     ReplyMsg((struct Message *)m);
  180.        End old stuff */
  181.  
  182.     return(t);
  183. }
  184.  
  185.  
  186. void thr_exit(thread t, int reason)
  187. {
  188.     t->em.header.mn_ReplyPort = t->port;
  189.     t->em.header.mn_Length = sizeof(_thmsg);
  190.     t->em.com = THC_EXIT;
  191.     t->em.data = (APTR)reason;
  192.     t->em.sender = t;
  193.     PutMsg(t->mother, (struct Message *)&t->em);
  194.  
  195.     while (1) {
  196.         thmsg m;
  197.         WaitPort(t->port);
  198.         m = (thmsg)GetMsg(t->port);
  199.         if (&t->em == m) break;
  200.         m->isreply = 1;
  201.         ReplyMsg((struct Message *)m);
  202.     }
  203.  
  204.     Forbid();
  205.     t->em.sender = t;
  206.     t->em.com = THC_FINISH;
  207.     PutMsg(t->mother, (struct Message *)&t->em);
  208.  
  209.     if (t->port) DeleteMsgPort(t->port);
  210. }
  211.  
  212.  
  213. void thr_message(thread t, int com, APTR data)
  214. {
  215.     thmsg m;
  216.  
  217.     m = malloc(sizeof(_thmsg));
  218.     if (!m) return;
  219.     memset(m, 0, sizeof(_thmsg));
  220.  
  221.     m->header.mn_ReplyPort = t->port;
  222.     m->header.mn_Length = sizeof(_thmsg);
  223.     m->sender = t;
  224.     m->com = com;
  225.     m->data = data;
  226.  
  227.     PutMsg(t->mother, (struct Message *)m);
  228. }
  229.  
  230.  
  231. /* private functions */
  232.  
  233. void th_handlemsg(thmsg m)
  234. {
  235.     if (m->com == THC_STARTUP) return;
  236.  
  237.     if (m->com == THC_FINISH) {
  238.         th_cleanup(m->sender);
  239.     }
  240.     else {
  241.         if (m->isreply) {
  242.             free(m);
  243.         }
  244.         else {
  245.             m->isreply = 1;
  246.             ReplyMsg((struct Message *)m);
  247.         }
  248.     }
  249. }
  250.  
  251.  
  252. void th_cleanup(thread t)
  253. {
  254.     if (th_list==t) {
  255.         th_list = t->next;
  256.     }
  257.     else {
  258.         thread tmp = th_list;
  259.         while (tmp) {
  260.             if (tmp->next==t) {
  261.                 tmp->next=t->next;
  262.                 break;
  263.             }
  264.             tmp = tmp->next;
  265.         }
  266.     }
  267.     free(t);
  268. }
  269.